﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace ExcelExportLib
{
    [XmlRoot("Worksheet")]
    public class ExcelTable:IXmlSerializable
    {
        private static StringBuilder sb = new StringBuilder();

        public List<ExcelRow> rows = new List<ExcelRow>();
        public List<ExcelColumn> columns = new List<ExcelColumn>();

        /// <summary>Table options, such as page setup or horizontal/vertical freezing</summary>
        public WorksheetOptions worksheetOptions = null;

        private int lastRowIndex = 0;

        public readonly string tableName;

        public ExcelTable(string name)
        {
            this.tableName = name;
        }
        public ExcelTable()
        {
            this.tableName = "Table 1";
        }

        /// <summary>Adds given row</summary>
        /// <param name="erow">ExcelRow to add</param>
        public void AddRow(ExcelRow erow)
        {
            lastRowIndex++;
            erow.index = lastRowIndex;
            rows.Add(erow);
            erow.parentTable = this;
        }
        /// <summary>Creates new row, adds it into table and returning this row</summary>
        /// <returns>Newly created and added row</returns>
        public ExcelRow AddRow()
        {
            ExcelRow er=new ExcelRow();
            AddRow(er);
            er.parentTable = this;
            return er;
        }
        /// <summary>Creates new row, adds it into table with position of index and returning this row</summary>
        /// <returns>Newly created and added row</returns>
        public ExcelRow AddRow(int index)
        {
            if (CheckRowIndex(index))
                throw new SystemException("Row with index " + index +" already exists!");

            if (lastRowIndex < index)
                lastRowIndex = index;

            ExcelRow er = new ExcelRow();
            er.index = index;
            AddRow(er);
            er.parentTable = this;
            return er;
        }

        /// <summary>Adds cell at given position. If row doesn't exists - adds new row</summary>
        public ExcelCell AddRow(ExcelCellPosition position, ExcelCell cell)
        {
            ExcelRow r = GetRowAtIndex(position.row);
            if (r == null)
                r = AddRow(position.row);
            r.parentTable = this;

            return r.AddCell(position.column, cell);
        }

        /// <summary>Adds given row at given index </summary>
        /// <param name="index">index of row</param>
        /// <param name="erow">row</param>
        public void AddRow(int index, ExcelRow erow)
        {
            if (CheckRowIndex(index))
                throw new SystemException("Row with index " + index + " already exists!");

            if (lastRowIndex < index)
                lastRowIndex = index;

            erow.index = index;
            rows.Add(erow);
            erow.parentTable = this;
        }

        /// <summary>Check if row with this index already exists </summary>
        /// <returns>true if row already exists</returns>
        public bool CheckRowIndex(int index)
        {
            foreach (ExcelRow row in rows)
                if(row.index==index)
                    return true;
            return false;
        }

        /// <summary>Finds row with given index </summary>
        /// <returns>ExcelRow with given index or null if nothing found</returns>
        public ExcelRow GetRowAtIndex(int index)
        {
            foreach (ExcelRow row in rows)
                if (row.index == index)
                    return row;
            return null;
        }

        /// <summary> Skipping one row. Next added row will be one row below</summary>
        public void SkipRow()
        {
            lastRowIndex++;
        }

        /// <summary> Skipping one row. Next added row will be n rows below</summary>
        public void SkipRow(int n)
        {
            lastRowIndex += n;
        }

        /// <summary>Adding column information</summary>
        /// <param name="autofit">autofit column. Warning: works only if column data is String or DateTime </param>
        /// <param name="width">Column width</param>
        public void AddColumn(bool autofit, int width)
        {
            columns.Add(new ExcelColumn(autofit, width));;
        }

        #region IXmlSerializable Members

        public System.Xml.Schema.XmlSchema GetSchema()
        {
            return null;
        }

        public void ReadXml(XmlReader reader)
        {
            throw new NotImplementedException();
        }

        public void WriteXml(XmlWriter writer)
        {
            writer.WriteExcelAttribute("Name", tableName); 

            writer.WriteStartElement("Table");

            foreach (ExcelColumn column in columns)
            {
                writer.WriteStartElement("Column");
                column.WriteXml(writer);
                writer.WriteEndElement();
            }

            foreach (ExcelRow row in rows)
            {
                writer.WriteStartElement("Row");
                row.WriteXml(writer);
                writer.WriteEndElement();
            }

            writer.WriteEndElement();

            //worksheetOptions
            if (worksheetOptions != null)
                worksheetOptions.WriteXml(writer);
        }

        #endregion
    }
}
